package com.adcc.ags.gms.user.service;

import com.adcc.ags.gms.core.entity.GWLogLevel;
import com.adcc.ags.gms.core.util.*;
import com.adcc.ags.gms.gw.service.SysConfigurationService;
import com.adcc.ags.gms.mq.entity.Queue;
import com.adcc.ags.gms.mq.mapper.QueueMapper;
import com.adcc.ags.gms.mq.vo.QueueVO;
import com.adcc.ags.gms.user.entity.BlackList;
import com.adcc.ags.gms.user.entity.GWUser;
import com.adcc.ags.gms.user.entity.Route;
import com.adcc.ags.gms.user.mapper.BlackListMapper;
import com.adcc.ags.gms.user.mapper.GWUserMapper;
import com.adcc.ags.gms.user.mapper.RouteMapper;
import com.adcc.ags.gms.user.vo.GWUserVO;
import com.adcc.utility.codec.MD5;
import com.adcc.utility.xml.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 网关用户服务层
 */
@Service("GWUserService")
public class GWUserServiceImpl implements GWUserService  {

    // 用户上线URL
    private final static String USER_ONLINE_URL = "/user/userOnline";

    // 用户下线URL
    private final static String USER_OFFLINE_URL = "/user/userOffline";

    // 网关用户配置更新URL
    private final static String USER_LIST_UPDATE_URL = "/user/updateUserList";

    // 网关用户历史文件
    private final static String USER_HIS_FILE_PATH = "/user_history";

    @Autowired
    private AppConfiguration configuration;

    @Autowired
    private GWUserMapper gwUserMapper;

    @Autowired
    private QueueMapper queueMapper;

    @Autowired
    private RouteMapper routeMapper;

    @Autowired
    private BlackListService blackListService;

    @Autowired
    private SysConfigurationService configurationService;

    @Autowired
    private BlackListMapper blackListMapper;

    @Autowired
    private LogFactory log;

    /**
     * 取得目标用户队列
     * @param id
     * @return
     */
    private String getDestQueue(String[] id){
        try{
            StringBuilder sb = new StringBuilder();
            if(id != null && id.length > 0){
                List<GWUser> list = gwUserMapper.findGWUserByIdList(id);
                if(list != null && list.size() > 0) {
                    for (int i = 0;i < list.size();i++) {
                        if(i == list.size()-1){
                            sb.append(list.get(i).getRecvQueueName());
                        }else{
                            sb.append(list.get(i).getRecvQueueName() + ",");
                        }
                    }
                }
            }
            return sb.toString();
        }catch (Exception ex){
            log.error(GWUserService.class, "MQ", GWLogLevel.ALARM, "查询用户目标队列失败",ex);
            return null;
        }
    }

    /**
     * 网关用户上线
     * @param gwUser
     * @param url
     * @return
     */
    private void gwUserOnline(GWUser gwUser,String url){
        CloseableHttpClient client = null;
        CloseableHttpResponse response = null;
        try{
            HttpPost httpPost = new HttpPost(url);
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectTimeout(5000)
                    .setSocketTimeout(5000)
                    .setConnectionRequestTimeout(120000).build();
            httpPost.setConfig(requestConfig);
            Map<String,Object> map = Maps.newConcurrentMap();
            map.put("id",gwUser.getUserId());
            map.put("name",gwUser.getUserName());
            map.put("msgType",gwUser.getDownlinkMsg());
            if(gwUser.getDownLinkForward() == 1){
                map.put("downlinkForword",true);
            }else{
                map.put("downlinkForword",false);
            }
            map.put("sendQueue",gwUser.getSendQueueName());
            map.put("recvQueue",gwUser.getRecvQueueName());
            if(gwUser.getRoutes() != null && gwUser.getRoutes().size() > 0){
                List<Map<String,Object>> list = Lists.newArrayListWithExpectedSize(100);
                for(Route route : gwUser.getRoutes()){
                    Map<String,Object> subMap = Maps.newHashMapWithExpectedSize(8);
                    subMap.put("id",route.getId());
                    subMap.put("name",route.getName());
                    subMap.put("type",route.getType());
                    if(route.getType() == 0){
                        if(!Strings.isNullOrEmpty(route.getSendAddress())){
                            subMap.put("sendAddress",route.getSendAddress());
                        }
                        if(!Strings.isNullOrEmpty(route.getRecvAddress())){
                            subMap.put("recvAddress",route.getRecvAddress());
                        }
                        if(!Strings.isNullOrEmpty(route.getSmi())){
                            subMap.put("smi",route.getSmi());
                        }
                        if(!Strings.isNullOrEmpty(route.getAn())){
                            subMap.put("an",route.getAn());
                        }
                        if(!Strings.isNullOrEmpty(route.getFi())){
                            subMap.put("fi",route.getFi());
                        }
                        if(!Strings.isNullOrEmpty(route.getRgs())){
                            subMap.put("rgs",route.getRgs());
                        }
                        if(!Strings.isNullOrEmpty(route.getSpecLable()) && route.getSpecIndex() != null && route.getSpecIndex() > -1){
                            subMap.put("specIndex",route.getSpecIndex());
                            subMap.put("specLabel",route.getSpecLable());
                        }
                    }else if(route.getType() == 1){
                        if(!Strings.isNullOrEmpty(route.getSendAddress())){
                            subMap.put("sendAddress",route.getSendAddress());
                        }
                        if(!Strings.isNullOrEmpty(route.getRecvAddress())){
                            subMap.put("recvAddress",route.getRecvAddress());
                        }
                        if(!Strings.isNullOrEmpty(route.getSmi())){
                            subMap.put("smi",route.getSmi());
                        }
                        if(!Strings.isNullOrEmpty(route.getAn())){
                            subMap.put("an",route.getAn());
                        }
                        if(!Strings.isNullOrEmpty(route.getSpecLable()) && route.getSpecIndex() != null && route.getSpecIndex() > -1){
                            subMap.put("specIndex",route.getSpecIndex());
                            subMap.put("specLabel",route.getSpecLable());
                        }
                        if(!Strings.isNullOrEmpty(route.getDestination())){
                            String[] strID = route.getDestination().split(",");
                            String strDestination = getDestQueue(strID);
                            if(!Strings.isNullOrEmpty(strDestination)){
                                subMap.put("destination",strDestination);
                            }
                        }
                    }else{
                        if(!Strings.isNullOrEmpty(route.getSpecLable()) && route.getSpecIndex() != null && route.getSpecIndex() > -1){
                            subMap.put("specIndex",route.getSpecIndex());
                            subMap.put("specLabel",route.getSpecLable());
                        }
                        if(!Strings.isNullOrEmpty(route.getDestination())){
                            String[] strID = route.getDestination().split(",");
                            String strDestination = getDestQueue(strID);
                            if(!Strings.isNullOrEmpty(strDestination)){
                                subMap.put("destination",strDestination);
                            }
                        }
                    }
                    list.add(subMap);
                }
                map.put("routes",list);
            }
            String strJSON = new ObjectMapper().writeValueAsString(map);
            List<BasicNameValuePair> list = Lists.newArrayListWithExpectedSize(1);
            list.add(new BasicNameValuePair("user",strJSON));
            httpPost.setEntity(new UrlEncodedFormEntity(list));
            client = HttpClients.createDefault();
            response = client.execute(httpPost);
            if(response.getStatusLine().getStatusCode() == 200){
                InputStream is = response.getEntity().getContent();
                Map<String,Object> m = new ObjectMapper().readValue(CommonUtil.getString(is),Map.class);
                String strResult = m.get("result").toString();
                if("SUCCESS".equals(strResult)){
                    log.info(GWUserService.class, "call " + url + " success");
                }else{
                    int intCode = Integer.valueOf(m.get("code").toString());
                    String strReason = m.get("reason").toString();
                    log.info(GWUserService.class, "call " + url + " fail code:" + intCode + " reason:" + strReason);
                }
            }else{
                log.error(GWUserService.class, "call " + url + " fail status code:" + response.getStatusLine().getStatusCode());
            }
        }catch (Exception ex){
            log.error(GWUserService.class,"gwUserOffline() error",ex);
        }finally {
            if(response != null){
                try {
                    response.close();
                } catch (IOException ex) {
                    log.error(GWUserService.class,"close IO error",ex);
                }
            }
            if(client != null){
                try {
                    client.close();
                } catch (IOException ex) {
                    log.error(GWUserService.class, "close IO error", ex);
                }
            }
        }
    }

    /**
     * 网关用户下线
     * @param gwUser
     * @param url
     * @return
     */
    private void gwUserOffline(GWUser gwUser,String url){
        CloseableHttpClient client = null;
        CloseableHttpResponse response = null;
        try{
            HttpPost httpPost = new HttpPost(url);
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(5000)
                    .setConnectTimeout(5000)
                    .setConnectionRequestTimeout(120000).build();
            httpPost.setConfig(requestConfig);
            List<BasicNameValuePair> list = Lists.newArrayListWithExpectedSize(2);
            list.add(new BasicNameValuePair("userId",gwUser.getUserId()));
            list.add(new BasicNameValuePair("userName",gwUser.getUserName()));
            httpPost.setEntity(new UrlEncodedFormEntity(list));
            client = HttpClients.createDefault();
            response = client.execute(httpPost);
            if(response.getStatusLine().getStatusCode() == 200){
                InputStream is = response.getEntity().getContent();
                Map<String,Object> m = new ObjectMapper().readValue(CommonUtil.getString(is),Map.class);
                String strResult = m.get("result").toString();
                if("SUCCESS".equals(strResult)){
                    log.info(GWUserService.class, "call " + url + " success");
                }else{
                    int intCode = Integer.valueOf(m.get("code").toString());
                    String strReason = m.get("reason").toString();
                    log.info(GWUserService.class, "call " + url + " fail code:" + intCode + " reason:" + strReason);
                }
            }else{
                log.error(GWUserService.class, "call " + url + " fail status code:" + response.getStatusLine().getStatusCode());
            }
        }catch (Exception ex){
            log.error(GWUserService.class,"gwUserOffline() error",ex);
        }finally {
            if(response != null){
                try {
                    response.close();
                } catch (IOException ex) {
                    log.error(GWUserService.class,"close IO error",ex);
                }
            }
            if(client != null){
                try {
                    client.close();
                } catch (IOException ex) {
                    log.error(GWUserService.class, "close IO error", ex);
                }
            }
        }
    }

    /**
     * 创建网关用户配置文件
     * @throws Exception
     */
    public String createUserListFile() throws Exception{
        XMLWriter xw = null;
        try{
            String strMD5 = "";

            // 如果网关用户配置文件不存在则创建文件路径
            String strFilePath = configuration.getGWUserFilePath();
            if(Strings.isNullOrEmpty(strFilePath)){
                throw new NullPointerException(strFilePath + " path is empty");
            }
            if(!FileUtil.mkdir(strFilePath)){
                throw new IOException("create " + strFilePath + " fail");
            }

            // 创建当前上线网关用户配置文件
            strFilePath += File.separator + Constant.USERLIST_FILE_NAME;
            Document document = createUserList();
            if(document != null){

                // 如果存在网关用户配置文件，则将其移动到历史文件夹中
                if(FileUtil.isExist(strFilePath)){

                    String strHisFilePath = configuration.getGWUserFilePath() + USER_HIS_FILE_PATH;
                    if(FileUtil.mkdir(strHisFilePath)){
                        String strFileName = "UserList_" + new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + ".xml";
                        strHisFilePath += File.separator + strFileName;
                        File file = new File(strFilePath);
                        FileUtil.mv(file,strHisFilePath);
                    }else {
                        log.error(GWUserService.class,"create " + strFilePath + " fail");
                    }
                }

                // 创建新的网关用户配置文件
                xw = new XMLWriter(new FileWriter(strFilePath), OutputFormat.createCompactFormat());
                xw.write(document);
                xw.flush();
                strMD5 = MD5.getMD5(document.asXML());
            }
            return strMD5;
        }catch (Exception ex){
            log.error(GWUserService.class,"updateUserList() error",ex);
            throw ex;
        }finally {
            if(xw != null){
                try {
                    xw.close();
                } catch (IOException ex) {
                    log.error(GWUserService.class,"close IO error",ex);
                }
            }
        }
    }

    @Override
    public Optional<Boolean> isExistGWUserName(String name) {
        try {
            int intCount = gwUserMapper.isExistGWUserName(name);
            if (intCount > 0) {
                return Optional.of(true);
            } else {
                return Optional.of(false);
            }
        } catch (Exception ex) {
            log.error(GWUserService.class, "GWUser", GWLogLevel.ALARM, "校验用户名称失败", ex);
            return Optional.absent();
        }
    }

    @Override
    public Optional<Boolean> isExistGWUserId(String userId) {
        try {
            int intCount = gwUserMapper.isExistGWUserId(userId);
            if (intCount > 0) {
                return Optional.of(true);
            } else {
                return Optional.of(false);
            }
        } catch (Exception ex) {
            log.error(GWUserService.class, "GWUser", GWLogLevel.ALARM, "校验用户ID失败", ex);
            return Optional.absent();
        }
    }

    @Override
    public Optional<List<GWUserVO>> findAllGWUser() {
        try {
            List<GWUserVO> result = Lists.newArrayListWithExpectedSize(1000);
            List<GWUser> list = gwUserMapper.findAllGWUser();
            if(list != null && list.size() > 0){
                for(GWUser user : list){
                    GWUserVO vo = new GWUserVO(user);
                    result.add(vo);
                }
            }
            return Optional.of(result);
        } catch (Exception ex) {
            log.error(GWUserService.class, "findAllGWUser() error", ex);
            return Optional.absent();
        }
    }

    @Override
    public Optional<List<QueueVO>> findUnusedQueue() {
        try{
            List<QueueVO> result = Lists.newArrayListWithExpectedSize(1000);
            List<Queue> QueueList = queueMapper.findByEnable("T");
            if(QueueList != null && QueueList.size()>0){
                List<Queue> userQueueList = gwUserMapper.findUsedQueue();
                if(userQueueList != null && userQueueList.size() > 0){
                    for(Queue queue : QueueList){
                        boolean flag = false;
                        for(Queue q : userQueueList){
                            if(q.getId().equals(queue.getId())){
                                flag = true;
                                break;
                            }
                        }
                        if(!flag){
                            QueueVO vo = new QueueVO(queue);
                            result.add(vo);
                        }
                    }

                }else{
                    for(Queue queue : QueueList){
                        QueueVO vo = new QueueVO(queue);
                        result.add(vo);
                    }
                }
            }
            return Optional.of(result);
        }catch (Exception ex){
            log.error(GWUserService.class, "GWUser", GWLogLevel.ALARM, "查询未使用队列失败", ex);
            return Optional.absent();
        }
    }

    @Override
    public Optional<List<QueueVO>> findUnusedRecvQueue() {
        try{
            List<QueueVO> result = Lists.newArrayListWithExpectedSize(1000);
            List<Queue> QueueList = queueMapper.findByEnable("T");
            if(QueueList != null && QueueList.size()>0){
                List<Queue> userQueueList = gwUserMapper.findUsedRecvQueue();
                if(userQueueList != null && userQueueList.size() > 0){
                    for(Queue queue : QueueList){
                        boolean flag = false;
                        for(Queue q : userQueueList){
                            if(q.getId().equals(queue.getId())){
                                flag = true;
                                break;
                            }
                        }
                        if(!flag){
                            QueueVO vo = new QueueVO(queue);
                            result.add(vo);
                        }
                    }

                }else{
                    for(Queue queue : QueueList){
                        QueueVO vo = new QueueVO(queue);
                        result.add(vo);
                    }
                }
            }
            return Optional.of(result);
        }catch (Exception ex){
            log.error(GWUserService.class, "GWUser", GWLogLevel.ALARM, "查询未使用接收队列失败", ex);
            return Optional.absent();
        }
    }

    @Override
    public Optional<PageInfo<GWUser>> findGWUserByName(String name,int currentPage, int pageSize) {
        try {
            String strName = Strings.nullToEmpty(name);
            if(!Strings.isNullOrEmpty(strName)){
                strName = "%" + strName + "%";
            }
            PageHelper.startPage(currentPage,pageSize);
            List<GWUser> list = gwUserMapper.findGWUserByName(strName);
            PageInfo<GWUser> pageInfo = new PageInfo<>(list);
            return Optional.of(pageInfo);
        } catch (Exception ex) {
            log.error(GWUserService.class,  "GWUser", GWLogLevel.ALARM, "查询网关用户失败", ex);
            return Optional.absent();
        }
    }

    @Override
    public Optional<Boolean> createGWUser(GWUserVO gwUserVO) {
        try {
            GWUser gwUser = gwUserVO.toEntity();
            gwUserMapper.createGWUser(gwUser);
            log.info(GWUserService.class, gwUserVO.getUserName(), "网关用户：" + gwUserVO.getUserName() + "新增");
            return Optional.of(true);
        } catch (Exception ex) {
            log.error(GWUserService.class, gwUserVO.getUserName(), GWLogLevel.ALARM, "网关用户：" + gwUserVO.getUserName() + "新增，失败", ex);
            return Optional.absent();
        }
    }

    @Override
    public Optional<Boolean> updateGWUser(GWUserVO user) {
        try {
            GWUser gwUser = user.toEntity();
            gwUserMapper.updateGWUser(gwUser);
            log.info(GWUserService.class, user.getUserName(), "网关用户：" + user.getUserName() + "修改");
            return Optional.of(true);
        } catch (Exception ex) {
            log.error(GWUserService.class, user.getUserName(), GWLogLevel.ALARM, "网关用户：" + user.getUserName() + "修改，失败", ex);
            return Optional.absent();
        }
    }

    @Override
    public Optional<Boolean> deleteGWUser(long id,Boolean flag) {
        String gwUserName = "";
        try {
            GWUser gwUser = gwUserMapper.findGWUserById(id);
            gwUserName= gwUser.getUserName();

            // 删除用户关联路由路由
            routeMapper.deleteRouteByGWUserId(id);

            //删除关联队列
            if(flag){
                //删除网关用户的发送队列

                //删除网关用户的接收队列
//                gwUserMapper.deleteRecvQueueByGWId(id);
            }

            // 如果网关用户在黑名单中,需要先删除黑名单用户
            List<BlackList> list = blackListMapper.findByCondition(id);
            if (list.size() > 0) {
                blackListMapper.deleteByGWUserId(id);
            }

            // 后删除网关用户
            gwUserMapper.deleteGWUser(id);

            log.info(GWUserService.class,gwUserName,"网关用户：" + gwUserName + "删除");
            return Optional.of(true);
        } catch (Exception e) {
            log.error(GWUserService.class, gwUserName, GWLogLevel.ALARM, "网关用户：" + gwUserName + "删除，失败", e);
            return Optional.absent();
        }
    }

    @Override
    public Optional<Boolean> gwUserOnline(long id) {
        String gwUserName = "";
        try {
            GWUser gwUser = gwUserMapper.findGWUserById(id);
            gwUserName = gwUser.getUserName();
            if(gwUser != null){
                gwUser.setStatus(1);
                gwUserMapper.updateGWUser(gwUser);
                String strUrl = configurationService.getValue(Constant.GW_SERVICE_URL) + USER_ONLINE_URL;
                gwUserOnline(gwUser, strUrl);
                log.info(GWUserService.class, gwUserName, "网关用户：" + gwUserName + "上线");
                return Optional.of(true);
            }else{
                log.error(GWUserService.class, gwUserName, GWLogLevel.ALARM, "网关用户：" + gwUserName + "上线，失败");
                return Optional.of(false);
            }
        } catch (Exception ex) {
            log.error(GWUserService.class, gwUserName, GWLogLevel.ALARM, "网关用户：" + gwUserName + "上线，失败",ex);
            return Optional.absent();
        }
    }

    @Override
    public Optional<Boolean> gwUserOffline(long id) {
        String gwUserName = "";
        try {
            GWUser gwUser = gwUserMapper.findGWUserById(id);
            gwUserName = gwUser.getUserName();
            if(gwUser != null){
                gwUser.setStatus(0);
                gwUserMapper.updateGWUser(gwUser);
                String strUrl = configurationService.getValue(Constant.GW_SERVICE_URL) + USER_OFFLINE_URL;
                gwUserOffline(gwUser, strUrl);
                log.info(GWUserService.class, gwUserName, "网关用户：" + gwUserName + "下线");
                return Optional.of(true);
            }else{
                log.error(GWUserService.class, gwUserName, GWLogLevel.ALARM, "网关用户：" + gwUserName + "下线，失败");
                return Optional.of(false);
            }
        } catch (Exception ex) {
            log.error(GWUserService.class, gwUserName, GWLogLevel.ALARM, "网关用户：" + gwUserName + "下线，失败", ex);
            return Optional.absent();
        }
    }

    /**
     * 创建网关用户列表
     * @return
     */
    public Document createUserList(){
        try{
            Document document = null;
            List<GWUser> list = gwUserMapper.findOnlineGWUser();
            if(list != null && list.size() > 0){
                ADCCXML adccxml  = ADCCXMLFactory.getInstance().createADCCXML();
                adccxml.getRoot().put("version","1");
                adccxml.getRoot().put("type","GWUserList");
                SuperNode superNode = new SuperNode("userList");
                for(GWUser gwUser : list){
                    Node node = new Node();
                    node.getAttributes().put("id",gwUser.getUserId());
                    node.getAttributes().put("name",gwUser.getUserName());
                    if(gwUser.getDownLinkForward() == 1){
                        node.getAttributes().put("downlinkForward","true");
                    }else {
                        node.getAttributes().put("downlinkForward","false");
                    }

                    Unit uSendQueue = new Unit();
                    uSendQueue.getAttributes().put("name","SendQueue");
                    uSendQueue.setText(gwUser.getSendQueueName());
                    node.getUnitList().add(uSendQueue);

                    Unit uRecvQueue = new Unit();
                    uRecvQueue.getAttributes().put("name","RecvQueue");
                    uRecvQueue.setText(gwUser.getRecvQueueName());
                    node.getUnitList().add(uRecvQueue);

                    Unit uType = new Unit();
                    uType.getAttributes().put("name","MsgType");
                    if(gwUser.getDownLinkForward() == 1){
                        uType.setText("SplitResult");
                    }else{
                        uType.setText("RawMsg");
                    }
                    node.getUnitList().add(uType);

                    if(gwUser.getRoutes() != null && gwUser.getRoutes().size() > 0){
                        for(Route route : gwUser.getRoutes()){
                            Node childNode = new Node(ADCCXML.CHILD_NODE_NAME);
                            childNode.getAttributes().put("id",route.getId().toString());
                            childNode.getAttributes().put("name",route.getName());
                            if(route.getType() == 1){
                                childNode.getAttributes().put("type","Uplink");

                                if(!Strings.isNullOrEmpty(route.getSendAddress())){
                                    Unit uSendAddress = new Unit();
                                    uSendAddress.getAttributes().put("name","SendAddress");
                                    uSendAddress.setText(route.getSendAddress());
                                    childNode.getUnitList().add(uSendAddress);
                                }

                                if(!Strings.isNullOrEmpty(route.getRecvAddress())){
                                    Unit uRecvAddress = new Unit();
                                    uRecvAddress.getAttributes().put("name","RecvAddress");
                                    uRecvAddress.setText(route.getRecvAddress());
                                    childNode.getUnitList().add(uRecvAddress);
                                }

                                if(!Strings.isNullOrEmpty(route.getSmi())){
                                    Unit uSMI = new Unit();
                                    uSMI.getAttributes().put("name","SMI");
                                    uSMI.setText(route.getSmi());
                                    childNode.getUnitList().add(uSMI);
                                }

                                if(!Strings.isNullOrEmpty(route.getAn())){
                                    Unit uAN = new Unit();
                                    uAN.getAttributes().put("name","AN");
                                    uAN.setText(route.getAn());
                                    childNode.getUnitList().add(uAN);
                                }

                                if(route.getSpecIndex() != null && route.getSpecIndex() > 0 && !Strings.isNullOrEmpty(route.getSpecLable())){
                                    Unit uSpecLabel = new Unit();
                                    uSpecLabel.getAttributes().put("name","SpecLabel");
                                    uSpecLabel.getAttributes().put("index",route.getSpecIndex().toString());
                                    uSpecLabel.setText(route.getSpecLable());
                                    childNode.getUnitList().add(uSpecLabel);
                                }

                                if(!Strings.isNullOrEmpty(route.getDestination())){
                                    String[] strID = route.getDestination().split(",");
                                    String strDestination = getDestQueue(strID);
                                    if(!Strings.isNullOrEmpty(strDestination)){
                                        Unit uDestination = new Unit();
                                        uDestination.getAttributes().put("name","Destination");
                                        uDestination.setText(strDestination);
                                        childNode.getUnitList().add(uDestination);
                                    }
                                }

                            }else if(route.getType() == 2){
                                childNode.getAttributes().put("type","Ground");

                                if(route.getSpecIndex() != null && route.getSpecIndex() > 0 && !Strings.isNullOrEmpty(route.getSpecLable())){
                                    Unit uSpecLabel = new Unit();
                                    uSpecLabel.getAttributes().put("name","SpecLabel");
                                    uSpecLabel.getAttributes().put("index",route.getSpecIndex().toString());
                                    uSpecLabel.setText(route.getSpecLable());
                                    childNode.getUnitList().add(uSpecLabel);
                                }

                                if(!Strings.isNullOrEmpty(route.getDestination())){
                                    String[] strID = route.getDestination().split(",");
                                    String strDestination = getDestQueue(strID);
                                    if(!Strings.isNullOrEmpty(strDestination)){
                                        Unit uDestination = new Unit();
                                        uDestination.getAttributes().put("name","Destination");
                                        uDestination.setText(strDestination);
                                        childNode.getUnitList().add(uDestination);
                                    }
                                }
                            }else{
                                childNode.getAttributes().put("type","Downlink");

                                if(!Strings.isNullOrEmpty(route.getSendAddress())){
                                    Unit uSendAddress = new Unit();
                                    uSendAddress.getAttributes().put("name","SendAddress");
                                    uSendAddress.setText(route.getSendAddress());
                                    childNode.getUnitList().add(uSendAddress);
                                }

                                if(!Strings.isNullOrEmpty(route.getRecvAddress())){
                                    Unit uRecvAddress = new Unit();
                                    uRecvAddress.getAttributes().put("name","RecvAddress");
                                    uRecvAddress.setText(route.getRecvAddress());
                                    childNode.getUnitList().add(uRecvAddress);
                                }

                                if(!Strings.isNullOrEmpty(route.getSmi())){
                                    Unit uSMI = new Unit();
                                    uSMI.getAttributes().put("name","SMI");
                                    uSMI.setText(route.getSmi());
                                    childNode.getUnitList().add(uSMI);
                                }

                                if(!Strings.isNullOrEmpty(route.getAn())){
                                    Unit uAN = new Unit();
                                    uAN.getAttributes().put("name","AN");
                                    uAN.setText(route.getAn());
                                    childNode.getUnitList().add(uAN);
                                }

                                if(!Strings.isNullOrEmpty(route.getFi())){
                                    Unit uFI = new Unit();
                                    uFI.getAttributes().put("name","FI");
                                    uFI.setText(route.getFi());
                                    childNode.getUnitList().add(uFI);
                                }

                                if(!Strings.isNullOrEmpty(route.getRgs())){
                                    Unit uRGS = new Unit();
                                    uRGS.getAttributes().put("name","RGS");
                                    uRGS.setText(route.getRgs());
                                    childNode.getUnitList().add(uRGS);
                                }

                                if(route.getSpecIndex() != null && route.getSpecIndex() > 0 && !Strings.isNullOrEmpty(route.getSpecLable())){
                                    Unit uSpecLabel = new Unit();
                                    uSpecLabel.getAttributes().put("name","uSpecLabel");
                                    uSpecLabel.getAttributes().put("index",route.getSpecIndex().toString());
                                    uSpecLabel.setText(route.getSpecLable());
                                    childNode.getUnitList().add(uSpecLabel);
                                }
                            }
                            node.getSubNodeList().add(childNode);
                        }
                    }
                    superNode.getNodeList().add(node);
                }
                adccxml.getSuperNodeList().add(superNode);
                document = adccxml.createXML();
            }
            return document;
        }catch (Exception ex){
            log.error(GWUserService.class,"createUserList() error",ex);
            return null;
        }
    }

    @Override
    public Optional<Boolean> updateUserList() {
        CloseableHttpClient client = null;
        CloseableHttpResponse response = null;
        try{
            String strMD5 = createUserListFile();
            if(!Strings.isNullOrEmpty(strMD5)){
                String strUrl = configurationService.getValue(Constant.GW_SERVICE_URL) + USER_LIST_UPDATE_URL;
                String strFilePath = configuration.getGWUserFilePath() + "/" + Constant.USERLIST_FILE_NAME;
                File file = new File(strFilePath);
                HttpPost httpPost = new HttpPost(strUrl);
                RequestConfig requestConfig = RequestConfig.custom()
                        .setSocketTimeout(5000)
                        .setConnectTimeout(5000)
                        .setConnectionRequestTimeout(120000).build();
                httpPost.setConfig(requestConfig);
                client = HttpClients.createDefault();
                MultipartEntityBuilder builder = MultipartEntityBuilder.create();
                builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
                builder.setCharset(Charset.forName("UTF-8"));
                HttpEntity entity = builder.addTextBody("MD5",strMD5).addPart("file", new FileBody(file)).build();
                httpPost.setEntity(entity);
                client.execute(httpPost);
                response = client.execute(httpPost);
                if(response.getStatusLine().getStatusCode() == 200){
                    InputStream is = response.getEntity().getContent();
                    Map<String,Object> m = new ObjectMapper().readValue(CommonUtil.getString(is),Map.class);
                    String strResult = m.get("result").toString();
                    if("SUCCESS".equals(strResult)){
                        log.info(GWUserService.class, "call " + strUrl + " success");
                        log.info(GWUserService.class, "GWUser", "网关用户推送");
                        return Optional.of(true);
                    }else{
                        int intCode = Integer.valueOf(m.get("code").toString());
                        String strReason = m.get("reason").toString();
                        log.error(GWUserService.class, "GWUser", GWLogLevel.ALARM, "网关用户推送，失败 " + "call " + strUrl + " fail code:" + intCode + " reason:" + strReason);
                        return Optional.absent();
                    }
                }else{
                    log.error(GWUserService.class, "GWUser", GWLogLevel.ALARM, "网关用户推送，失败 " + "call " + strUrl + " fail status code:" + response.getStatusLine().getStatusCode());
                    return Optional.absent();
                }
            }else{
                log.error(GWUserService.class, "GWUser", GWLogLevel.ALARM, "网关用户推送，失败");
                return Optional.of(false);
            }
        }catch (Exception ex){
            log.error(GWUserService.class, "GWUser", GWLogLevel.ALARM, "网关用户推送，失败",ex);
            return Optional.absent();
        }finally {
            if(response != null){
                try {
                    response.close();
                } catch (IOException ex) {
                    log.error(GWUserService.class,"close IO error",ex);
                }
            }
            if(client != null){
                try {
                    response.close();
                } catch (IOException ex) {
                    log.error(GWUserService.class,"close IO error",ex);
                }
            }
        }
    }

    @Override
    public List<GWUser> findByQueueId(Long queueId) {
        List<GWUser> list = null;
        try {
            list = gwUserMapper.findByQueueId(queueId);
        } catch (Exception e) {
            log.error(GWUserService.class, "findByQueueId() error", e);
        }
        return list;
    }
}

